﻿using System;
using System.Threading.Tasks;
using System.Windows.Input;

using Windows.UI.Xaml;

using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;

using Uhimania.Libraries.Test;

using Uhimania.Libraries.Windows.Interactivity;

namespace Windows.InteractivityTest
{
    [TestClass]
    public class InvokeCommandActionTest
    {
        #region Command

        #region 正常ケース
        [TestMethod]
        public async Task Command_正常ケース()
        {
            await UiTestHelper.ExecuteOnUiThread(() =>
            {
                var mock = new CommandMock();
                var action = new InvokeCommandAction();
                action.Command = mock;
                action.Command.Is(mock);
            });
        }
        #endregion

        #endregion

        #region CommandParameter

        #region 正常ケース
        [TestMethod]
        public async Task CommandParameter_正常ケース()
        {
            await UiTestHelper.ExecuteOnUiThread(() =>
            {
                var obj = new object();
                var action = new InvokeCommandAction();
                action.CommandParameter = obj;
                action.CommandParameter.Is(obj);
            });
        }
        #endregion

        #endregion

        #region Invoke

        #region 正常ケース
        [TestMethod]
        public async Task Invoke_正常ケース()
        {
            await UiTestHelper.ExecuteOnUiThread(() =>
            {
                var mock = new CommandMock();

                var action = new InvokeCommandAction();
                action.Attach(new Mock());
                action.Command = mock;
                action.CommandParameter = "foo";

                action.AsDynamic().Invoke("bar");

                mock.executed.Is(true);
                mock.parameter.Is("foo");
            });
        }
        #endregion

        #region CanExecuteがfalse
        [TestMethod]
        public async Task Invoke_CanExecuteがfalse()
        {
            await UiTestHelper.ExecuteOnUiThread(() =>
            {
                var mock = new CommandMock();
                mock.canExecute = false;

                var action = new InvokeCommandAction();
                action.Attach(new Mock());
                action.Command = mock;

                action.AsDynamic().Invoke("bar");

                mock.executed.Is(false);
                mock.parameter.IsNull();
            });
        }
        #endregion

        #region Commandがnull
        [TestMethod]
        public async Task Invoke_Commandがnull()
        {
            await UiTestHelper.ExecuteOnUiThread(() =>
            {
                var action = new InvokeCommandAction();
                action.Attach(new Mock());
                action.AsDynamic().Invoke("bar");
            });
        }
        #endregion

        #region CommandParameterがnull
        [TestMethod]
        public async Task Invoke_CommandParameterがnull()
        {
            await UiTestHelper.ExecuteOnUiThread(() =>
            {
                var mock = new CommandMock();

                var action = new InvokeCommandAction();
                action.Attach(new Mock());
                action.Command = mock;
                action.CommandParameter = null;

                action.AsDynamic().Invoke("bar");

                mock.executed.Is(true);
                mock.parameter.Is(null);
            });
        }
        #endregion

        #endregion

        #region Mock

        private class Mock : DependencyObject
        {
        }

        private class CommandMock : ICommand
        {
            public bool canExecute = true;
            public bool CanExecute(object parameter)
            {
                return this.canExecute;
            }

            public event EventHandler CanExecuteChanged;

            public bool executed = false;
            public object parameter;
            public void Execute(object parameter)
            {
                this.executed = true;
                this.parameter = parameter;
            }
        }

        #endregion
    }
}
